<?php 
/*
	Copyright 2010 Ping Shin Ching (ping_sc@hotmail.com)

	Licensed under the Apache License, Version 2.0 (the "License");
	you may not use this file except in compliance with the License.
	You may obtain a copy of the License at

		http://www.apache.org/licenses/LICENSE-2.0

	Unless required by applicable law or agreed to in writing, software
	distributed under the License is distributed on an "AS IS" BASIS,
	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
	See the License for the specific language governing permissions and
	limitations under the License.
	
	Project Mugatiya: http://www.tidytutorials.com/p/mugatiya.html
 */
 
/*
ini_set('display_errors', 1); 
ini_set('log_errors', 1); 
error_reporting(E_ALL);
*/

$myheaderstogo = array();

require_once 'defaultopts.php';
require_once 'supercaptcha.php';
require_once 'grokkers.php';
require_once 'postrequest.php';
require_once 'regxs.php';
require_once 'blockedips.php';
require_once 'config.php';
require_once 'helpers.php';

/*I*/ require_once 'spr/Impfunctions.php';


/*
 * Maximum time for the process to run. This may interfere with streaming.
 */
set_time_limit(180);


$httpStatus;
$sub_req_url="";
$sub_req_host="";
$output="";
$rating="";
$contentType="";
$headers="";


/* These are for the writefunction called via CURLOPT_WRITEFUNCTION */
$finishedheaders=0;
$redirectincallback=0;
$collect=1;
$binarymodifyfunctionref=FALSE;


$sub_req_url = $_SERVER['REQUEST_URI'];


/*
 * This is for the index page.
 */
if(strcasecmp($sub_req_url, "/")==0){
	header("Location: $myhost/".INDEX_PAGE);
	exit(0);
}


/*
 * Reverse any of the re-written https urls.
 * Re-initialize $sub_req_url reversing any HTTPS stuff
 */
$sub_req_url = grokReverseHTTPS($_SERVER['REQUEST_URI']);
if(isset($_SERVER['HTTP_HOST']))
	$sub_req_host=$_SERVER['HTTP_HOST'];

/*
 * Stop it immediately if it's a CONNECT Request.
 */

 
if(strcasecmp($_SERVER['REQUEST_METHOD'], "CONNECT")==0){
	error_log("Connect request - $sub_req_url");
	header("HTTP/1.0 407 Access Denied");

	exit(0);
}

/*
 * Stop it immediately if it's asking to connect to a specific port
 */
if(preg_match("/http:\/\/[^\/]+(:(\d+))/", $sub_req_url, $matches)){
	if(($portno=intval($matches[2]))!=80 && $portno<1024){
		error_log("Trying to connect to port other than 80 $portno - $sub_req_url");
		header("Location: $myhost/".NOACCESS_PAGE);
		exit(0);
	}
}
	
/*
 * Check to see if it should be in the walled garden
 * or if it should be blocked.
 */
$inthegarden=0;
foreach($walledgarden as $gardenpatch => $w_go){
	if(stripos($sub_req_host, $gardenpatch)!==FALSE){
		if($w_go)
			$inthegarden=1;
		else{
			header("Location: $myhost/".NOACCESS_PAGE);exit(0);	
		}
	}
}
foreach($walledurls as $w_url => $w_go){
	if(stripos($sub_req_url, $w_url)!==FALSE){
		if($w_go)
			$inthegarden=1;	
		else{
			header("Location: $myhost/".NOACCESS_PAGE);exit(0);
		}
	}
}

/*
 * Check to see if the the requesting IP and or the site requested is banned
 */
if(!$inthegarden){
	$remoteip=getremoteip($_SERVER);
	foreach($blocked_ips as $blockedip => $hits){
		if ( $remoteip == $blockedip){
			if($hits < TOTALCUTOFF){
				break;
			}
			else{
				print file_get_contents(BLOCKED_PAGE);
				error_log("BLOCKED");
				exit(0);
			}
		}
	}
	if(TURINGTEST && !checkifhuman($remoteip)){
		header("Location: $myhost/messages/in_checkifhuman.php?url=".urlencode($sub_req_url));
		exit(0);	
	
	}
	//If it's an naked internal Ip then block it.
	if( $sub_req_host=="" || preg_match("/^(192|172|10)\.\d+\.\d+\.\d+(:\d+)?$/ims", $sub_req_host)){
		header("Location: $myhost/".NOACCESS_PAGE);exit(0);
	}
}


/*
 * Initialize curl !!!!!!!
 */
$ch = curl_init();

/*
 * Set the default curl options and copy any headers to the outgoing request 
 */
//$_SERVER["HTTP_X_FORWARDED_FOR_P"]=$_SERVER["REMOTE_ADDR"];
if(isset($_SERVER['HTTP_REFERER']))
	curl_setopt($ch, CURLOPT_REFERER, $_SERVER['HTTP_REFERER']);
setdefaultoptions($ch, $_SERVER, $sub_req_url);
curl_setopt($ch, CURLOPT_URL, $sub_req_url);

/*
 * Some extra care if the method is a POST request
 */
$encoded="";
if(strstr($_SERVER['REQUEST_METHOD'], "POST")){
	
	/*I*/$_POST=imodpostvalues($sub_req_url, $sub_req_host, $_POST);
	
	$encoded = getencodedpost($_POST);

	if(grokIsHostReversed($sub_req_host)===FALSE && POSTSPAMTEST && checkpostforspam($encoded)){
		header("Location: $myhost/".POSTSPAM_PAGE);
		exit(0);
	}
	curl_setopt($ch, CURLOPT_POST, 1);
	curl_setopt($ch, CURLOPT_POSTFIELDS,  $encoded);
}

if(($x=curl_exec($ch))===FALSE){
	error_log(curl_error($ch));
	curl_close($ch);
	header("Location: $myhost/".ERROR_PAGE);
	exit(0);
}

/*
 * Close the curl connection
 */
curl_close($ch);

/*
 * If there was a redirrect in thewritefunction handle it here.
 */
if($redirectincallback){
	$loc = grokLocation($headers, 1);
	$loc = preg_replace_callback(TRUEHTTPS_REGX, "grokTrueHTTPS", $loc);
	header("Location: $loc");
	exit(0);
}

if(!$collect){
//ignore binary data
}
else{
	if($binarymodifyfunctionref!==FALSE){
		call_user_func($binarymodifyfunctionref, $output);
		//echo $output;
	}
	else{
		ob_start("ob_gzhandler");
		/*
		 *  Replace any URLs and add the banners 
		 */
		if((stripos($contentType, "text")!==FALSE ||
			stripos($contentType, "javascript")!==FALSE) &&
			!$inthegarden){
			
			/* Change any https links to go via http. */
			$output = preg_replace_callback(TRUEHTTPS_REGX, "grokTrueHTTPS", $output);
			
			if(preg_match("/\b(html)\b/ims", $contentType)){
				/*I*/ $output=imodresponse($output);	
			}
		}
		/*
		* Send the output back to the client !!!!!!!!!!!!!!!!!!!!!
		*/
		echo $output;
		/*
		 * Flush all the output
		 */
		ob_end_flush();
	}
}
//error_log("Get: $rating $sub_req_url");	
//END//

/*
 * the writefunction callback for CURLOPT_WRITEFUNCTION
 */
function writefunction($ch, $data){
	global $output,	
	$contentType, $sub_req_url, $httpStatus, $finishedheaders,
	$redirectincallback, $headers, $collect,
	$binarymodifyfunctionref;

	if(!$collect){
 		echo $data;
 	}
 	else{
		$output .= $data;
		if(!$finishedheaders && ($headers=grokTheHeadersAndRemoveThem($output))!=NULL){
			$finishedheaders=1;
			$contentType 	= curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
			$sub_req_url	= curl_getinfo($ch, CURLINFO_EFFECTIVE_URL);
			$httpStatus 	= curl_getinfo($ch, CURLINFO_HTTP_CODE);

			/* Set the statusline and headers and cookies for the reply */
 			header(grokStatusline($headers));
		
			grokSetCookies($headers, 1);

			if(isset($contentType) && $contentType!=""){
				header("Content-type: $contentType");
				if(stripos($contentType, "text")!==FALSE){
					$collect=1;
				}
				else if(($binarymodifyfunctionref=imodmodifybinary($contentType))!==FALSE){
					$collect=1;
				}
				else{
					$collect=0;
					echo $output;
				}
			}
				
			if($httpStatus>=300 && $httpStatus<400){
				$redirectincallback=1;
			}
 		}
 	}
	return strlen($data);	
}
?>
